package com.tuniu.agents.evaluators.common.impl;

import com.google.gson.JsonObject;
import com.tuniu.agents.advisor.ChatEnvironmentMemory;
import com.tuniu.agents.common.AgentsConstants;
import com.tuniu.agents.common.entity.cart.Cart;
import com.tuniu.agents.common.entity.cart.CartItem;
import com.tuniu.agents.common.entity.cart.FlightCartItem;
import com.tuniu.agents.common.entity.cart.HotelCartItem;
import com.tuniu.agents.evaluator.EvaluationResult;
import com.tuniu.agents.evaluators.common.AbstractEvaluator;
import com.tuniu.agents.evaluators.common.EvaluatorProperties;
import com.tuniu.agents.evaluators.common.entity.FavoriteRequest;
import com.tuniu.agents.evaluators.common.entity.FavoriteResponse;
import com.tuniu.agents.impl.evaluator.EvaluatorAgentConfig;
import com.tuniu.agents.util.HttpManager;
import com.tuniu.agents.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;


/**
* Cart Evaluator
* Used to evaluate various metrics of the shopping cart
*/

@Component
@Slf4j
public class CartEvaluator extends AbstractEvaluator<Cart> {

    private static final String NAME = "CART_EVALUATOR"; // Evaluator name
    private static final String DESCRIPTION = "Evaluate various metrics of the shopping cart and provide recommendations"; // Evaluator description

    private final EvaluatorProperties properties;

    // API for retrieving favorites list
    private String favoriteUrl;


    @Autowired
    private HttpManager httpManager;

    @Autowired
    private ChatEnvironmentMemory chatEnvironmentMemory;

   public CartEvaluator(EvaluatorProperties properties) {
       super(NAME, DESCRIPTION);
       this.properties = properties;
       favoriteUrl = properties.getFavoriteUrl();
   }

    @Override
    public EvaluationResult evaluate(String conversationId, String queryId) {
        return null;
    }

    @Override
   public boolean supports(Cart target) {
       return target != null;
   }

   /**
    * Preprocess the data
    * Retrieve data from API or database
    * @param conversationId Conversation ID
    * @param queryId Query ID
    * @return Shopping cart
    */
   @Override
   protected Cart preEvaluate(String conversationId, String queryId) {

       try {
           // Retrieve favorites data from API
           FavoriteResponse queryFavoriteList = queryFavorite(conversationId);
        
           if (queryFavoriteList != null && queryFavoriteList.getData() != null && 
               queryFavoriteList.getData().getData() != null && 
               queryFavoriteList.getData().getData().getRows() != null && 
               queryFavoriteList.getData().getData().getRows().size() > 0) {
               List<CartItem> selectItems = queryFavoriteList.getData().getData().getRows().stream()
                   .filter(row -> row.getSnapshotId() == Long.parseLong(queryId))
                   .map(row->{
                       CartItem cartItem = new CartItem();
                       CartItem childItem = convertToCartItem(row);
                       cartItem.setSnapshotId(row.getSnapshotId());
                       cartItem.setResType(row.getResType());
                       cartItem.setStatus(row.getStatus());
                       cartItem.setDepartureCityName(row.getDepartureCityName());
                       cartItem.setArrivalCityName(row.getArrivalCityName());
                       cartItem.setDepartDate(row.getDepartDate());
                       cartItem.setParamType(row.getParamType());
                       cartItem.setUserId(row.getUserId());
                       cartItem.setAddTime(row.getAddTime());
                       cartItem.setParams(childItem);

                       return cartItem;
                   })
                   .collect(Collectors.toList());
               if(selectItems != null && !selectItems.isEmpty()){
                   // Exclude resources of the same type as the selected ones
                   List<CartItem> packageItems = queryFavoriteList.getData().getData().getRows().stream()
                       .filter(row -> row.getSnapshotId() != Long.parseLong(queryId) && row.getResType() != selectItems.get(0).getResType())
                       .map(row->{
                       CartItem cartItem = new CartItem();
                       CartItem childItem = convertToCartItem(row);
                       cartItem.setSnapshotId(row.getSnapshotId());
                       cartItem.setResType(row.getResType());
                       cartItem.setStatus(row.getStatus());
                       cartItem.setDepartureCityName(row.getDepartureCityName());
                       cartItem.setArrivalCityName(row.getArrivalCityName());
                       cartItem.setDepartDate(row.getDepartDate());
                       cartItem.setParamType(row.getParamType());
                       cartItem.setUserId(row.getUserId());
                       cartItem.setAddTime(row.getAddTime());
                       cartItem.setParams(childItem);
                       return cartItem;
                   })
                   .collect(Collectors.toList());

                   Cart cart = new Cart();
                   cart.setSelectItems(selectItems);
                   cart.setPackageItems(packageItems);
                   return cart;
               }
           }
           return new Cart();
       } catch (Exception e) {
           e.printStackTrace();
       }
       return null;
   }

    @Override
    protected Cart preEvaluateByUserId(String userId, String conversationId) {
        return null;
    }

    /**
    * Convert favorites data for different product categories
    * @param row
    * @return
    */
   private CartItem convertToCartItem(FavoriteResponse.Favorite row) {
       CartItem cartItem = new CartItem();
       try {
           switch (row.getResType()) {
               case 130: // Hotel
                   // Parse hotel parameters
                    cartItem = JsonUtil.fromJson(row.getParams(), HotelCartItem.class);
                   break;

               case 21: // Flight
                    cartItem = JsonUtil.fromJson(row.getParams(), FlightCartItem.class);
                    break;

               default:
               break;

           }
       } catch (Exception e) {
           e.printStackTrace();

       }
       return cartItem;
   }

   @Override
   protected EvaluationResult doEvaluate(Cart cart) {
       if(agent == null){
           getAgent();
       }
       String packageItemsString = cart.getPackageItemsString();
       String selectedItemsString = cart.getSelectItemsString();
        ChatResponse chatResponse = agent.callResponse( UUID.randomUUID().toString(), selectedItemsString+"|"+packageItemsString);
       EvaluationResult evaluationResult = getEvaluationResult(chatResponse);
       log.info("CartEvaluator doEvaluate :evaluationResult:{}",chatResponse.getResult().getOutput().getText());
        return evaluationResult;
   }

    @Override
    protected Flux<String> doEvaluateFlux(Cart target) {
        return null;
    }

    @Override
   protected void getAgent() {
       agent = agentManager.getAgent(EvaluatorAgentConfig.CART_EVALUATOR_AGENT_ID);
   }

   private EvaluationResult getEvaluationResult(ChatResponse chatResponse){
       String agentResult = chatResponse.getResult().getOutput().getText();
       String jsonContent = JsonUtil.getJsonString(agentResult);
       JsonObject jsonObject = JsonUtil.fromJson(jsonContent, JsonObject.class);
       // Parse the response from the large language model
       String result = jsonObject.has("result") && !jsonObject.get("result").isJsonNull() ? jsonObject.get("result").getAsString() : "";
       String recommend = jsonObject.has("recommend") && !jsonObject.get("recommend").isJsonNull() ? jsonObject.get("recommend").getAsString() : "";
       String reason = jsonObject.has("reason") && !jsonObject.get("reason").isJsonNull() ? jsonObject.get("reason").getAsString() : "";
      return EvaluationResult.Builder.newBuilder()
               .evaluatorName(getName())
               .success(Boolean.parseBoolean(result))
               .message(reason)
               .addRecommendation(recommend)
               .build();

   }

   private FavoriteResponse queryFavorite(String conversationId){
    String userId =  chatEnvironmentMemory.get(conversationId,AgentsConstants.AgentsConversationEnvironmentKey.CUSTOMER_ID)!=null ? chatEnvironmentMemory.get(conversationId,AgentsConstants.AgentsConversationEnvironmentKey.CUSTOMER_ID).toString() : "0";
    log.info("queryFavorite :conversationId:{},userId:{}",conversationId,userId);
    FavoriteRequest favoriteRequest = new FavoriteRequest(Long.parseLong(userId));
    log.info("queryFavorite :favoriteRequest:{}",favoriteRequest);
    FavoriteResponse favoriteResponse = httpManager.post(favoriteUrl, favoriteRequest, FavoriteResponse.class);
    log.info("queryFavorite :favoriteResponse:{}",JsonUtil.toJson(favoriteResponse));
     return favoriteResponse;
   }

   @Override
   protected String checkEvaluateResult(String userId,Cart target) {
       return null;
   }

   

}
